#
# Package.
#

package iSOCK::Model::DFS;

#
# Parent.
#

use Moose;
use namespace::autoclean;

BEGIN { extends 'iSOCK::Model::Root' }

no Moose;

#
# Dependencies.
#

use HTML::TableExtract;
use HTTP::Request::Common;
use List::MoreUtils qw( mesh );
use LWP::UserAgent;
use Net::LDAP;
use Readonly;
use Sort::Naturally qw( ncmp );

#
# Documentation.
#

=head1 NAME

iSOCK::Model::DFS - Catalyst Model

=head1 DESCRIPTION

Catalyst Model.

=head1 AUTHOR

Xavier Caron

=head1 LICENSE

This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

#
# Constants.
#

Readonly my $LDAP_HOST => 'rfodc01.rfo.atmel.com';
Readonly my $LDAP_USER => 'CORP\\rfoflowweb';
Readonly my $LDAP_PASS => 'Mdp4fl0ww3b';
Readonly my $LDAP_BASE => 'dc=corp,dc=atmel,dc=com';

Readonly my $DFS_HOST  => 'papenoo.rfo.atmel.com';

#
# Functions.
#

sub component_lineup {
  my ( $self, $option ) = @_;
  
  my ( $c, $product_id, $dummy ) = map { $option->{$_} } qw( c product_id dummy );
  
  if ( my $product_r = $c->model ( 'App::Product' )->find ( $product_id ) ) {
    my $mech = WWW::Mechanize->new ( noproxy => 1 );

    ( my $dfs_product_id = $product_id ) =~ s/-//;

    my $ldap = Net::LDAP->new ( $LDAP_HOST );
    
    $ldap->bind ( $LDAP_USER, password => $LDAP_PASS ) if $ldap;
        
    if ( my $ua = LWP::UserAgent->new ) {
      my $url = "http://$DFS_HOST:8080/dfs/ldr.php";

      $ua->no_proxy ( $DFS_HOST );

      my $response = $ua->request ( POST $url => [ hiddenProd => $dfs_product_id ] );

      if ( $response->is_success ) {
        my $hoh = {
          product_id    => $product_id,
          product_scope => 'dfs',
          dfs_url       => $url,
        };
        
        my $extractor = HTML::TableExtract->new ( headers => [ 'Library/Asc. Ref', 'Function/Comment', 'Version', 'Update', 'Owner' ] );

        $extractor->parse ( $response->decoded_content );

        my $loh;

        if ( $extractor->tables ) {
          my @columns = qw( name description version update owner );

          for ( $extractor->rows ) {
            my @values = map { s/[\n\r\t]//gm ; $_ } @$_;

            my $h = { mesh @columns, @values };

            $h->{name} =  uc $h->{name};
            $h->{name} =~ s/^ASC//;

            if ( $h->{name} =~ /^CORTEX/i ) {
              $h->{type} = undef; # FIXME create core type?
            }
            elsif ( my $component_r = $c->model ( 'App::Component' )->find ( $h->{name} ) ) {
              $h->{type} = $component_r->type_id;
            }
            elsif ( my $type = $self->component_type_from_ldap ( $ldap, $h->{owner} ) ) {
              $h->{type} = $type;

              if ( $h->{type} eq 'memory' ) {
                $h->{version} = 0;
              }
              
              $h->{guessed} = 1;
            }

            if ( $h->{type} ) {
              push @$loh, $h;
            }
          }
        }
        
        if ( $loh ) {
          $hoh->{components} = [ sort { ncmp $a->{name}, $b->{name} } @$loh ];
        }

        $ldap->unbind if $ldap;
        
        return $hoh;
      }
    }
    
    $ldap->unbind if $ldap;
  }

  return;  
}

sub component_type_from_ldap {
  my ( $self, $ldap, $name ) = @_;
  
  my $map = {
    'MCU IP & ANALOG'      => 'analog',
    'Design Kits& Library' => 'digital',
   #'MCU Product Design'   => 'memory',
  };
  
  my @values;
  
  if ( $ldap ) {
    my ( $surname, $family ) = ( $name =~ /^ (.+) \s+ (\S+) $/x );

    if ( $surname && $family ) {
      my $attribute = 'department';
      my $message   = $ldap->search ( base => $LDAP_BASE, filter => "(&(sn=$family)(givenName=$surname))", attrs => [ $attribute ] );

         @values    = map { $_->get_value ( $attribute ) } $message->entries;
    }
  }
    
  unless ( @values ) {
   #return 'digital' if $name eq 'TSMC';
    return;
  }
  
  if ( @values == 1 ) {
    return $map->{$values[0]};
  }
  
  return;
}

#
# True.
#

1;
